<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JS030-图片放大镜案例</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    body {
        background-color: #222;
        color: snow;
    }

    ul {
        list-style: none;
    }

    .container {
        height: 50rem;

        margin: 1rem;
        padding: 1rem;
        border: 1px solid silver;
    }

    .album-cover {
        position: relative;
        display: flex;
        gap: 1rem;

        cursor: move;

        .middle {
            position: relative;
            width: 20rem;
            height: 20rem;

            img {
                width: 100%;
                height: 100%;
                object-fit: cover;
            }

            .zoom-scope {
                position: absolute;
                top: 0;
                left: 0;
                width: 50%;
                height: 50%;
                display: none;
                background-color: rgba(0, 0, 0, .3);
            }
        }

        .small {
            height: 20rem;

            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: space-between;
            gap: .5rem;

            overflow-y: auto;
            scrollbar-width: thin;
            scrollbar-color: #777 #333;

            li {
                width: 5rem;
                height: 5rem;

                flex-shrink: 0;
                display: flex;
                align-items: center;
                justify-content: center;

                background-repeat: no-repeat;
                background-position: center;
                background-size: contain;

                border: 1px solid transparent;

                &.active {
                    border-color: silver;
                }
            }
        }

        .large {
            position: absolute;
            top: 20.5rem;

            width: 20rem;
            height: 20rem;

            display: none;

            border: 1px solid silver;

            background-size: 200%;
            background-repeat: no-repeat;
        }
    }
</style>
<body>
<div class="container">
    <h1 style="margin-bottom: 1rem;">JS030-图片放大镜案例</h1>
    <div class="album-cover">
        <div class="middle">
            <img src="" alt="album-cover-image">
            <div class="zoom-scope"></div>
        </div>
        <ul class="small"></ul>
        <div class="large"></div>
    </div>
</div>

<script>
    const albums = [{
        album_title: 'Abbey Road',
        album_artist: 'The Beatles',
        album_cover_url: 'https://s2.loli.net/2025/09/30/AOaX2xgHwriTfhS.jpg',
    }, {
        album_title: 'Physical Graffiti',
        album_artist: 'Led Zeppelin',
        album_cover_url: 'https://s2.loli.net/2024/05/11/GWFgsm8Lc9HPi7K.jpg',
    }, {
        album_title: 'Scary Monsters (and Super Creeps)',
        album_artist: 'David Bowie',
        album_cover_url: 'https://s2.loli.net/2024/05/14/uQTXJD8G5A2YLZx.jpg',
    }];

    const middleCoverBoxEl = document.querySelector('.album-cover .middle');
    const middleCoverImageEl = middleCoverBoxEl.querySelector('img');
    const smallCoverListEl = document.querySelector('.album-cover .small');
    const largeCoverBoxEl = document.querySelector('.album-cover .large');
    const middleCoverBoxZoomScopeEl = document.querySelector('.album-cover .middle .zoom-scope');
    let largeCoverBoxElHideTimerId = -1;

    albums.forEach((album, index) => {
        const smallCoverEl = document.createElement('li');
        smallCoverEl.style.backgroundImage = `url(${album.album_cover_url})`;
        smallCoverEl.addEventListener('mouseenter', function () {
            if (this.classList.contains('active')) return;
            smallCoverListEl.querySelector('li.active').classList.remove('active');
            this.classList.add('active');
            middleCoverImageEl.src = album.album_cover_url;
        });
        //初始默认选择第一个
        if (index === 0) {
            smallCoverEl.classList.add('active');
            middleCoverImageEl.src = album.album_cover_url;
        }
        smallCoverListEl.appendChild(smallCoverEl);
    });

    middleCoverBoxEl.addEventListener('mouseenter', function () {
        showZoomEls(middleCoverImageEl.src);
    });
    largeCoverBoxEl.addEventListener('mouseenter', showZoomEls);
    middleCoverBoxEl.addEventListener('mousemove', function (e) {
        let boxRect = middleCoverBoxEl.getBoundingClientRect();
        let zoomRect = middleCoverBoxZoomScopeEl.getBoundingClientRect();
        let htmlScrollTop = document.documentElement.scrollTop;
        let htmlScrollLeft = document.documentElement.scrollLeft;

        // 计算鼠标相对于盒子的坐标
        let mouseX = e.pageX - boxRect.left - htmlScrollLeft;
        let mouseY = e.pageY - boxRect.top - htmlScrollTop;

        // 限制放大镜不超出盒子边界
        // 左、上边界：left=0, top=0
        // 右、下边界：left=boxWidth-zoomWidth, top=boxHeight-zoomHeight
        // 中间值：left=mouseX-zoomWidth/2, top=mouseY-zoomHeight/2
        // JS没有clamp函数，只能嵌套max和min函数实现
        let x = Math.max(0, Math.min(mouseX - zoomRect.width / 2, boxRect.width - zoomRect.width));
        let y = Math.max(0, Math.min(mouseY - zoomRect.height / 2, boxRect.height - zoomRect.height));

        middleCoverBoxZoomScopeEl.style.left = `${x}px`;
        middleCoverBoxZoomScopeEl.style.top = `${y}px`;

        largeCoverBoxEl.style.backgroundPositionX = `${-2 * x}px`;
        largeCoverBoxEl.style.backgroundPositionY = `${-2 * y}px`;

    });
    middleCoverBoxEl.addEventListener('mouseleave', hideZoomEls);

    function showZoomEls(coverImageUrl) {
        clearTimeout(largeCoverBoxElHideTimerId);
        if (coverImageUrl)
            largeCoverBoxEl.style.backgroundImage = `url(${coverImageUrl})`;
        largeCoverBoxEl.style.display = 'block';
        middleCoverBoxZoomScopeEl.style.display = 'block';
    }

    function hideZoomEls() {
        largeCoverBoxElHideTimerId = setTimeout(() => {
            largeCoverBoxEl.style.display = 'none';
            middleCoverBoxZoomScopeEl.style.display = 'none';
        }, 200);
    }
</script>
</body>
</html>